/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 *
 */

import { hvigorCore, TaskDetails } from '@ohos/hvigor';

import { findTargetProduct } from '../../common/find-target-product.js';
import { ArktSTaskConst } from '../../const/common-const.js';
import { AbstractModulePlugin } from '../../plugin/common/abstract-module-plugin.js';
import { InjectUtil } from '../../utils/inject-util.js';
import { isFastBuildApp } from '../../utils/task-util.js';
import { BuildNativeWithCmake } from '../build-native-with-cmake.js';
import { CollectDebugSymbol } from '../collect-debug-symbol.js';
import { Clean } from '../common/clean.js';
import { TaskNames } from '../common/task-names.js';
import { CompileResource } from '../compile-resource.js';
import { BuildHotReloadResource } from '../debugger/build-hot-reload-resource.js';
import { HotReloadBuild } from '../debugger/hot-reload-build.js';
import { DeviceTestHook } from '../device-test-hook.js';
import { FastPackageHap } from '../fast-package.js';
import { GenerateLoaderJson } from '../generate-loader-json.js';
import { GeneratedBuildProfileTask } from '../generated-build-profile-task.js';
import { AssembleHap } from '../hook/assemble/assemble-hap.js';
import { AssembleHar } from '../hook/assemble/assemble-har.js';
import { AssembleHqf } from '../hook/assemble/assemble-hqf.js';
import { AssembleHsp } from '../hook/assemble/assemble-hsp.js';
import { GenOnDeviceTestHap } from '../hook/gen-on-device-test-hap.js';
import { CompileNativeHook } from '../hook/native/compile-native-hook.js';
import { PreviewHookCompileResource } from '../hook/preview-hook-compile-resource.js';
import { BuildHarPreviewerRes } from '../hook/previewer/build-har-previewer-res.js';
import { BuildPreviewerRes } from '../hook/previewer/build-previewer-res.js';
import { PreviewBuild } from '../hook/previewer/preview-build.js';
import { FastPackageHsp } from '../hsp/fast-package-hsp.js';
import { PackageSharedTgz } from '../hsp/package-shared-tgz.js';
import { LegacyHookCompileResource } from '../legacy-tasks/hook/legacy-hook-compile-resource.js';
import { LegacyGenerateHarJsManifest } from '../legacy-tasks/legacy-generate-har-js-manifest.js';
import { LegacyGenerateHarLoaderJson } from '../legacy-tasks/legacy-generate-har-loader-json.js';
import { LegacyGenerateJsManifest } from '../legacy-tasks/legacy-generate-js-manifest.js';
import { LegacyGenerateLoaderJson } from '../legacy-tasks/legacy-generate-loader-json.js';
import { LegacyPackageHap } from '../legacy-tasks/legacy-package-hap.js';
import { PackageHap } from '../package-hap.js';
import { PreCheckSyscap } from '../pre-check-syscap.js';
import { PreviewCompileResource } from '../preview-compile-resource.js';
import { ReplacePreviewerPage } from '../previewer/replace-previewer-page.js';
import { ModuleTaskService } from '../service/module-task-service.js';
import { SignHap } from '../sign-hap.js';
import { GlobalTaskCreator, TargetTaskCreator } from '../task-creator.js';
import { Test } from '../unitTest/test.js';
import { UnitTestBuild } from '../unitTest/unit-test-build.js';

export class AssembleHqfCA extends GlobalTaskCreator {
  constructor(service: ModuleTaskService, plugin: AbstractModulePlugin, isFa?: boolean) {
    AssembleHqf.isAdd = true;
    AssembleHqf.versionCode = undefined;
    super(service, plugin, isFa);
  }
  declareDepends = () => [TaskNames.Task.SIGN_HQF.name];

  declareTaskDetail = () => TaskNames.CommonHookTask.ASSEMBLE_HQF;

  provider = () => new AssembleHqf(this.service);
}

export class AssembleHapCA extends GlobalTaskCreator {
  declareDepends = () => {
    const depends = [CollectDebugSymbol.name]; // 增加任务依赖CollectDebugSymbol

    if (isFastBuildApp(this.service)) {
      depends.push(FastPackageHap.name);
      return depends;
    }

    if (findTargetProduct(this.service.getProjectModel()).buildOption?.packOptions?.buildAppSkipSignHap &&
      hvigorCore.isCommandEntryTask(TaskNames.CommonHookTask.ASSEMBLE_APP.name)) {
      this.isFa ? depends.push(LegacyPackageHap.name) : depends.push(PackageHap.name);
      return depends;
    } else {
      depends.push(SignHap.name);
      return depends;
    }
  };

  declareTaskDetail = () => TaskNames.CommonHookTask.ASSEMBLE_HAP;

  provider = () => new AssembleHap(this.service, this.isFa);
}

export class GenOnDeviceTestHapCA extends GlobalTaskCreator {
  declareDepends = () => {
    if (
      findTargetProduct(this.service.getProjectModel()).buildOption?.packOptions?.buildAppSkipSignHap &&
      hvigorCore.isCommandEntryTask(TaskNames.CommonHookTask.ASSEMBLE_APP.name)
    ) {
      return this.isFa ? [LegacyPackageHap.name] : [PackageHap.name];
    }
    return [SignHap.name];
  };

  declareTaskDetail = () => TaskNames.CommonHookTask.GEN_ON_DEVICE_TEST_HAP;

  provider = () => new GenOnDeviceTestHap(this.service, this.isFa);
}

export class AssembleHspCA extends GlobalTaskCreator {
  declareDepends = () => {
    if (isFastBuildApp(this.service)) {
      return [FastPackageHsp.name, CollectDebugSymbol.name];
    }

    return [PackageSharedTgz.name, CollectDebugSymbol.name];
  };

  declareTaskDetail = () => TaskNames.CommonHookTask.ASSEMBLE_HSP;

  provider = () => new AssembleHsp(this.service, this.isFa);
}

export class PreviewHookCompileResourceCA extends TargetTaskCreator {
  provider = () => new PreviewHookCompileResource(this.targetService);

  declareDepends = (): string[] => {
    const isIncremental: boolean = this.targetService.getSdkInfo().isPreviewCompileResourceIncrement(this.targetService.getTargetData().isHarmonyOS());
    return [isIncremental ? PreviewCompileResource.name : CompileResource.name];
  };

  declareTaskDetail = (): TaskDetails => TaskNames.CommonTask.PREVIEW_HOOK_COMPILE_RESOURCE;
}

export class AssembleHarCA extends GlobalTaskCreator {
  declareDepends = () => {
    const depends = [this.isFa ? TaskNames.LegacyFATask.PACKAGE_HAR.name : TaskNames.CommonTask.PACKAGE_SIGN_HAR.name];
    depends.push(CollectDebugSymbol.name);
    return depends;
  };

  declareTaskDetail = () => TaskNames.CommonHookTask.ASSEMBLE_HAR;

  provider = () => new AssembleHar(this.service, this.isFa);
}

export class LibraryBuildPreviewerResCA extends GlobalTaskCreator {
  declareDepends(): string[] {
    const depends: string[] = [];
    if (this.isFa) {
      depends.push(LegacyGenerateHarLoaderJson.name, LegacyGenerateHarJsManifest.name);
    } else {
      depends.push(GenerateLoaderJson.name, PreviewHookCompileResource.name);
    }

    depends.push(PreCheckSyscap.name);
    return depends;
  }

  declareTaskDetail = () => TaskNames.CommonHookTask.BUILD_PREVIEWER_RES;

  provider = () => new BuildHarPreviewerRes(this.service, this.isFa);
}

export class BuildPreviewerResCA extends GlobalTaskCreator {
  declareDepends(): string[] {
    const depends: string[] = [];
    if (this.isFa) {
      depends.push(LegacyGenerateLoaderJson.name, LegacyGenerateJsManifest.name, LegacyHookCompileResource.name);
    } else {
      depends.push(GenerateLoaderJson.name, ReplacePreviewerPage.name);
    }
    depends.push(PreCheckSyscap.name);

    return depends;
  }

  declareTaskDetail = () => TaskNames.CommonHookTask.BUILD_PREVIEWER_RES;

  provider = () => new BuildPreviewerRes(this.service, this.isFa);
}

export class HotReloadBuildCA extends GlobalTaskCreator {
  declareDepends = () => ['HotReloadArkTS'];

  declareTaskDetail = () => TaskNames.Task.HOT_RELOAD_BUILD;

  provider = () => new HotReloadBuild(this.service);
}

export class GeneratedBuildProfileCA extends GlobalTaskCreator {
  private isHar = false;

  constructor(service: ModuleTaskService, plugin: AbstractModulePlugin, isFa: boolean, isHar?: boolean) {
    super(service, plugin, isFa);
    this.isHar = isHar === undefined ? false : isHar;
  }

  declareDepends = (): string[] => {
    return [this.isHar ? TaskNames.CommonTask.CREATE_HAR_BUILD_PROFILE.name : TaskNames.CommonTask.CREATE_BUILD_PROFILE.name];
  };

  declareTaskDetail = () => TaskNames.CommonHookTask.GENERATE_BUILD_PROFILE;

  provider = () => new GeneratedBuildProfileTask(this.service, this.isHar);
}

export class PreviewBuildCA extends GlobalTaskCreator {
  declareDepends = () => [this.isFa ? 'LegacyPreviewCompileArkTS' : 'PreviewArkTS'];

  declareTaskDetail = () => TaskNames.Task.PREVIEW_BUILD;

  provider = () => new PreviewBuild(this.service, this.isFa);
}

export class CompileNativeHookCA extends GlobalTaskCreator {
  declareDepends = () => [BuildNativeWithCmake.name];

  declareTaskDetail = () => TaskNames.CommonHookTask.COMPILE_NATIVE;

  provider = () => new CompileNativeHook(this.service);
}

export class CleanCA extends GlobalTaskCreator {
  declareDepends = () => [];

  declareTaskDetail = () => TaskNames.CommonTask.CLEAN;

  provider = () => new Clean(this.service.getNode(), this.service);
}

export class UnitTestBuildCA extends GlobalTaskCreator {
  declareDepends = () => {
    if (this.isFa) {
      return [ArktSTaskConst.LEGACY_UNIT_TEST_ARKTS];
    }
    if (InjectUtil.isOhosTestCoverage()) {
      return [TaskNames.Task.REPLACE_SOURCEMAP_IN_COVERAGE_MODE.name];
    }
    return [ArktSTaskConst.UNIT_TEST_ARKTS, TaskNames.Task.UNIT_TEST_COPY_MOCK_CONFIG_JSON.name];
  };

  declareTaskDetail = () => TaskNames.Task.UNIT_TEST_BUILD;

  provider = () => new UnitTestBuild(this.service, this.isFa);
}

export class TestCA extends GlobalTaskCreator {
  declareDepends = () => [TaskNames.Task.GENERATE_UNIT_TEST_RESULT.name];

  declareTaskDetail = () => TaskNames.Task.TEST;

  provider = () => new Test(this.service, this.isFa);
}

export class DeviceTestHookCA extends GlobalTaskCreator {
  declareDepends = () => {
    return [TaskNames.Task.GENERATE_DEVICE_COVERAGE.name];
  };

  declareTaskDetail = () => TaskNames.Task.ON_DEVICE_TEST;

  provider = () => new DeviceTestHook(this.service, this.isFa);
}

export class BuildHotReloadResourceCA extends GlobalTaskCreator {
  declareDepends = (): string[] => [GenerateLoaderJson.name, CompileResource.name];

  declareTaskDetail = () => TaskNames.CommonHookTask.BUILD_HOT_RELOAD_RES;

  provider = () => new BuildHotReloadResource(this.service);
}
